// ==================== src/memory/config_storage.rs ====================
//! 内存配置存储实现

use async_trait::async_trait;
use nacos_core::{ConfigStorage, ConfigItem, Result, Storage};
use std::sync::Arc;
use super::MemoryStorage;
use tracing::{debug, trace};

/// 内存配置存储实现
#[derive(Debug, Clone)]
pub struct MemoryConfigStorage {
    storage: Arc<MemoryStorage>,
}

impl MemoryConfigStorage {
    /// 创建新的内存配置存储实例
    pub fn new() -> Self {
        Self {
            storage: Arc::new(MemoryStorage::new()),
        }
    }
    
    /// 从现有存储创建
    pub fn from_storage(storage: Arc<MemoryStorage>) -> Self {
        Self { storage }
    }
    
    /// 生成配置键
    fn config_key(&self, namespace: &str, group: &str, data_id: &str) -> String {
        format!("config:{}:{}:{}", namespace, group, data_id)
    }
    
    /// 生成配置列表键前缀
    fn config_prefix(&self, namespace: &str, group: Option<&str>) -> String {
        match group {
            Some(g) => format!("config:{}:{}:", namespace, g),
            None => format!("config:{}:", namespace),
        }
    }
    
    /// 生成配置历史键
    fn config_history_key(&self, namespace: &str, group: &str, data_id: &str, version: u64) -> String {
        format!("config_history:{}:{}:{}:{}", namespace, group, data_id, version)
    }
}

impl Default for MemoryConfigStorage {
    fn default() -> Self {
        Self::new()
    }
}

#[async_trait]
impl ConfigStorage for MemoryConfigStorage {
    async fn get_config(&self, namespace: &str, group: &str, data_id: &str) -> Result<Option<ConfigItem>> {
        trace!("Getting config: namespace={}, group={}, data_id={}", namespace, group, data_id);
        
        let key = self.config_key(namespace, group, data_id);
        
        if let Some(data) = self.storage.get(&key).await? {
            let config: ConfigItem = serde_json::from_slice(&data)?;
            debug!("Found config: {}", key);
            Ok(Some(config))
        } else {
            debug!("Config not found: {}", key);
            Ok(None)
        }
    }
    
    async fn save_config(&self, config: &ConfigItem) -> Result<()> {
        trace!("Saving config: namespace={}, group={}, data_id={}", 
               config.namespace, config.group, config.data_id);
        
        let key = self.config_key(&config.namespace, &config.group, &config.data_id);
        let data = serde_json::to_vec(config)?;
        
        self.storage.put(&key, &data).await?;
        
        // 保存历史版本
        let history_key = self.config_history_key(&config.namespace, &config.group, &config.data_id, config.version);
        self.storage.put(&history_key, &data).await?;
        
        debug!("Saved config: {}", key);
        Ok(())
    }
    
    async fn delete_config(&self, namespace: &str, group: &str, data_id: &str) -> Result<()> {
        trace!("Deleting config: namespace={}, group={}, data_id={}", namespace, group, data_id);
        
        let key = self.config_key(namespace, group, data_id);
        self.storage.delete(&key).await?;
        
        // 删除历史版本
        let history_prefix = format!("config_history:{}:{}:{}:", namespace, group, data_id);
        let history_items = self.storage.scan(&history_prefix).await?;
        
        for (history_key, _) in history_items {
            self.storage.delete(&history_key).await?;
        }
        
        debug!("Deleted config: {}", key);
        Ok(())
    }
    
    async fn list_configs(&self, namespace: &str, group: Option<&str>) -> Result<Vec<ConfigItem>> {
        trace!("Listing configs: namespace={}, group={:?}", namespace, group);
        
        let prefix = self.config_prefix(namespace, group);
        let items = self.storage.scan(&prefix).await?;
        
        let mut configs = Vec::new();
        for (_, data) in items {
            let config: ConfigItem = serde_json::from_slice(&data)?;
            configs.push(config);
        }
        
        debug!("Listed {} configs for namespace={}, group={:?}", configs.len(), namespace, group);
        Ok(configs)
    }
    
    async fn get_config_history(&self, namespace: &str, group: &str, data_id: &str, limit: usize) -> Result<Vec<ConfigItem>> {
        trace!("Getting config history: namespace={}, group={}, data_id={}, limit={}", 
               namespace, group, data_id, limit);
        
        let prefix = format!("config_history:{}:{}:{}:", namespace, group, data_id);
        let items = self.storage.scan(&prefix).await?;
        
        let mut configs = Vec::new();
        for (_, data) in items {
            let config: ConfigItem = serde_json::from_slice(&data)?;
            configs.push(config);
        }
        
        // 按版本号倒序排序
        configs.sort_by(|a, b| b.version.cmp(&a.version));
        
        // 限制返回数量
        configs.truncate(limit);
        
        debug!("Retrieved {} config history items", configs.len());
        Ok(configs)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use nacos_core::ConfigItem;

    fn create_test_config(data_id: &str, group: &str, content: &str) -> ConfigItem {
        ConfigItem::new(data_id.to_string(), group.to_string(), content.to_string())
    }

    #[tokio::test]
    async fn test_save_and_get_config() {
        let storage = MemoryConfigStorage::new();
        let config = create_test_config("test-id", "test-group", "content");

        storage.save_config(&config).await.unwrap();

        let retrieved = storage.get_config("public", "test-group", "test-id").await.unwrap().unwrap();
        assert_eq!(config, retrieved);
    }

    #[tokio::test]
    async fn test_delete_config() {
        let storage = MemoryConfigStorage::new();
        let config = create_test_config("test-id", "test-group", "content");
        storage.save_config(&config).await.unwrap();

        storage.delete_config("public", "test-group", "test-id").await.unwrap();

        let retrieved = storage.get_config("public", "test-group", "test-id").await.unwrap();
        assert!(retrieved.is_none());
    }

    #[tokio::test]
    async fn test_list_configs() {
        let storage = MemoryConfigStorage::new();
        storage.save_config(&create_test_config("id1", "group1", "c1")).await.unwrap();
        storage.save_config(&create_test_config("id2", "group1", "c2")).await.unwrap();
        storage.save_config(&create_test_config("id3", "group2", "c3")).await.unwrap();

        let group1_configs = storage.list_configs("public", Some("group1")).await.unwrap();
        assert_eq!(group1_configs.len(), 2);

        let all_configs = storage.list_configs("public", None).await.unwrap();
        assert_eq!(all_configs.len(), 3);
    }

    #[tokio::test]
    async fn test_config_history() {
        let storage = MemoryConfigStorage::new();
        let mut config = create_test_config("history-id", "history-group", "v1");
        storage.save_config(&config).await.unwrap();

        config.content = "v2".to_string();
        config.version = 2;
        storage.save_config(&config).await.unwrap();

        let history = storage.get_config_history("public", "history-group", "history-id", 5).await.unwrap();
        assert_eq!(history.len(), 2);
        assert_eq!(history[0].version, 2);
        assert_eq!(history[1].version, 1);
    }
}
